#include <iostream>
#include <typeinfo>

// value propagation
void swap_value(int a, int b)
{

    std::cout << "typeid(a).name() = " << typeid(a).name() << std::endl;

    int temp = a;
    a = b;
    b = temp;
    std::cout << "value propagation: &a = " << &a << std::endl; // 这里的 a 是 main函数中 a 的一个拷贝，和 a 除了值一样之外，没有任何联系
    std::cout << "value propagation: &a = " << &b << std::endl;
}

void swap_reference(int &a, int &b)
{
    std::cout << "typeid(a).name() = " << typeid(a).name() << std::endl;
    int temp = a;
    a = b;
    b = temp;
    std::cout << "reference propagation: &a = " << &a << std::endl; // 形参中的 a 是一个引用类型，可以理解为就是 a 本身传过来了，所以这个地址和 main 函数中的地址是一样的
    std::cout << "reference propagation: &b = " << &b << std::endl;
}

void swap_address(int *a, int *b)
{
    std::cout << "typeid(a).name() = " << typeid(a).name() << std::endl;
    int temp = *a;
    *a = *b;
    *b = temp;
    std::cout << "address propagation: &a = " << &a << std::endl; // 这儿 a 是函数中的形参，而形参是一个的指针，也就是这个 a 是一个指针，&a 则是 a 的地址，指针的地址
    std::cout << "address propagation: &b = " << &b << std::endl;

    std::cout << "address propagation: a = " << a << std::endl; // 在这儿 a 是直接传过来的地址，所以这个地址和 main 函数中的 a 地址是相同的
    std::cout << "address propagation: b = " << b << std::endl; 

    std::cout << "address propagation: *a = " << *a << std::endl; // *a 是对 指针 a 的一个解指针操作，得到的是值
    std::cout << "address propagation: *b = " << *b << std::endl;

}

int main(int argc, char const *argv[])
{
    int a = 100;
    int b = 200;

    std::cout << "Before\n";
    std::cout << "a = " << a << std::endl;
    std::cout << "b = " << b << std::endl;

    std::cout << "&a = " << &a << std::endl;
    std::cout << "&b = " << &b << std::endl;

    swap_value(a, b);
    // swap_reference(a, b);
    // swap_address(&a, &b);

    std::cout << "After\n";
    std::cout << "a = " << a << std::endl;
    std::cout << "b = " << b << std::endl;

    std::cout << "&a = " << &a << std::endl;
    std::cout << "&b = " << &b << std::endl;

    return 0;
}

/*

Value Propagation

    Before
        a = 100
        b = 200
        &a = 0x7fffffffe010
        &b = 0x7fffffffe014
        typeid(a).name() = i
        value propagation: &a = 0x7fffffffdfdc
        value propagation: &a = 0x7fffffffdfd8
    After
        a = 100
        b = 200
        &a = 0x7fffffffe010
        &b = 0x7fffffffe014


Reference Propagation

    Before
        a = 100
        b = 200
        &a = 0x7fffffffe010
        &b = 0x7fffffffe014
        typeid(a).name() = i
        reference propagation: &a = 0x7fffffffe010
        reference propagation: &b = 0x7fffffffe014
    After
        a = 200
        b = 100
        &a = 0x7fffffffe010
        &b = 0x7fffffffe014


Address Propagation

    Before
        a = 100
        b = 200
        &a = 0x7fffffffe010
        &b = 0x7fffffffe014
        typeid(a).name() = Pi
        address propagation: &a = 0x7fffffffdfd8
        address propagation: &b = 0x7fffffffdfd0
        address propagation: a = 0x7fffffffe010
        address propagation: b = 0x7fffffffe014
        address propagation: *a = 200
        address propagation: *b = 100
    After
        a = 200
        b = 100
        &a = 0x7fffffffe010
        &b = 0x7fffffffe014


*/